package com.devunion.bogdan.view.editors;

import com.devunion.bogdan.model.project.Project;
import com.devunion.bogdan.model.project.Page;
import com.devunion.bogdan.model.project.Annotation;
import com.devunion.bogdan.model.project.AnnotationType;
import com.devunion.bogdan.model.event.AnnotationListener;
import com.devunion.bogdan.model.event.AnnotationEvent;
import com.devunion.bogdan.model.UserManager;
import com.devunion.bogdan.view.actions.annotations.EditorToolbarManager;

import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.*;

import org.apache.log4j.Logger;

/**
 * @author Viktar Liaskovich
 */
public class DefaultEditorHolder extends JPanel implements EditorHolder {
    private static Logger log = Logger.getLogger(DefaultEditorHolder.class);

    private final Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
            BasicStroke.JOIN_BEVEL, 1, new float[]{5, 5}, 0);

    private boolean shouldErase;
    private int x, y;

    private Point startPoint = null;
    private Point endPoint = null;
    private Page page;

    private AnnotationManager annotationManager;
    private ComponentFactory componentFactory;

    private boolean paintBorder = false;
    private boolean showAnnotations = true;

    private float zoomRatio = 1;

    private boolean updatingRequired = false;

    private Project project;
//    private final ProjectFileManager fileManager = new ProjectFileManager();
//    private final MyActiveFileListener activeFileListener = new MyActiveFileListener();

    private boolean projectClosing;
    private MediaTracker tracker = new MediaTracker(this);
    private AnnotationListener annotationListener = new MyAnnotationListener();

    public DefaultEditorHolder() {
        super(null);

        initManagers();

        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {

                    if (EditorToolbarManager.getInstance().isAddTextAnnotationToolSelected() ||
                            EditorToolbarManager.getInstance().isAddImageAnnotationToolSelected()) {
                        startPoint = e.getPoint();
                    }
                }
            }

            private AnnotationType getAnnotationType() {
                if (EditorToolbarManager.getInstance().isAddTextAnnotationToolSelected()) {
                    return AnnotationType.TEXT;
                }
                if (EditorToolbarManager.getInstance().isAddImageAnnotationToolSelected()) {
                    return AnnotationType.IMAGE;
                }
                return null;
            }

            public void mouseReleased(MouseEvent e) {
                if (startPoint != null) {
                    endPoint = e.getPoint();
                    shouldErase = false;

                    if (endPoint.distance(startPoint) > 24) {
                        Point leftTopPoint = CoordinateHelper.getLeftTopPoint(startPoint, endPoint);
                        int width = CoordinateHelper.getWidth(startPoint, endPoint);
                        int height = CoordinateHelper.getHeight(startPoint, endPoint);

                        Annotation annotation = new Annotation(
                                (int) (leftTopPoint.x / zoomRatio),
                                (int) (leftTopPoint.y / zoomRatio),
                                (int) (width / zoomRatio),
                                (int) (height / zoomRatio),
                                getAnnotationType()
                        );

                        annotation.setOwner(UserManager.getInstance().getUser());

                        page.addAnnotation(annotation);
                    } else {
                        annotationManager.getSelectionManager().setSelectionForAll(false);
                    }

                    startPoint = null;
                    endPoint = null;

                    updateUI();
                } else {
                    annotationManager.getSelectionManager().setSelectionForAll(false);
                }
            }
        });

        addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseDragged(MouseEvent e) {
                if (startPoint != null) {
                    Graphics2D g = (Graphics2D) getGraphics();
                    g.setXORMode(Color.WHITE);

                    if (shouldErase) {
                        g.setStroke(stroke);
                        g.drawRect((int) Math.min(startPoint.getX(), x), (int) Math.min(startPoint.getY(), y), (int) Math.abs(x - startPoint.getX()),
                                (int) Math.abs(y - startPoint.getY()));
                    }

                    x = e.getX();
                    y = e.getY();

                    g.setStroke(stroke);
                    g.drawRect((int) Math.min(startPoint.getX(), x), (int) Math.min(startPoint.getY(), y), (int) Math.abs(x - startPoint.getX()),
                            (int) Math.abs(y - startPoint.getY()));
                    g.dispose();

                    shouldErase = true;
                }
            }
        });
    }

    private void initManagers() {
        annotationManager = AnnotationManager.getInstance();
        componentFactory = annotationManager.getComponentFactory();
    }

    private void removeComponent(Annotation a) {
        Component view = annotationManager.model2View(a);
        annotationManager.removeComponent(view);
    }

    private JComponent placeComponent(Annotation annotation) {

        JComponent component = componentFactory.createView(annotation);
        ((AnnotationView) component).setRatio(zoomRatio);

        add(component);

        component.setBounds(
                (int) (annotation.getX() * zoomRatio),
                (int) (annotation.getY() * zoomRatio),
                (int) (annotation.getWidth() * zoomRatio),
                (int) (annotation.getHeight() * zoomRatio)
        );

//        ComponentInfo info = annotationManager.getComponentInfo(component);
//        info.setSelected(true);
        annotationManager.getSelectionManager().setSelection(component, true);

        paintBorder = true;

        return component;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (page != null && page.getImageObject() != null) {
            int width = getWidth();
            int height = getHeight();

//            g.drawImage(backgroundImage, 0, 0, width, height, this);

            int w = (int) (page.getImageObject().getWidth(null) * zoomRatio);
            int h = (int) (page.getImageObject().getHeight(null) * zoomRatio);


            if (updatingRequired) {
                Dimension d = new Dimension(w, h);

                setPreferredSize(d);

                for (Component c : getComponents()) {
                    ((AnnotationView) c).setRatio(zoomRatio);
                    c.repaint();
                }

//                ((JViewport) getParent()).revalidate();
                ((JScrollPane) getParent().getParent()).revalidate();

                updatingRequired = false;
            }

            g.drawImage(page.getImageObject(), 0, 0, w, h, null);

//
//            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//            Graphics2D biContext = bi.createGraphics();
//            biContext.drawImage(backgroundImage, 0, 0, null);
        }
    }

    public void setPage(Page page) {
        if (this.page != null) {
            this.page.removeAnnotationListener(annotationListener);
        }

        if (this.page != null) {
            for (Annotation a : this.page.getAnnotations()) {
                removeComponent(a);
            }
        }

        this.page = page;

        for (Annotation a : page.getAnnotations()) {
            placeComponent(a);
        }

        this.page.addAnnotationListener(annotationListener);

        try {
            tracker.addImage(page.getImageObject(), 0);
            tracker.waitForID(0);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        updatePreferedSize();
    }

    public void zoom(int zoomPercent) {
        zoomRatio = zoomPercent / 100f;

        updatingRequired = true;
        repaint();
    }

    private void updatePreferedSize() {
        int w = (int) (page.getImageObject().getWidth(null) * zoomRatio);
        int h = (int) (page.getImageObject().getHeight(null) * zoomRatio);

        setPreferredSize(new Dimension(w, h));
    }

    public void onPorjectClose() {
        removeAll();
    }

    public void showAnnotations(boolean value) {
        if (value == showAnnotations) {
            return;
        }

        showAnnotations = value;

        for (Component c : getComponents()) {
            c.setVisible(showAnnotations);
        }

        repaint();
    }

    private class MyAnnotationListener implements AnnotationListener {
        public void annotationAdded(AnnotationEvent e) {

            JComponent c = placeComponent(e.getAnnotation());
            c.grabFocus();

            setCursor(Cursor.getDefaultCursor());
            if (!paintBorder) {
                annotationManager.getSelectionManager().setSelectionForAll(false);
            }
        }

        public void annotationRemoved(AnnotationEvent e) {
            Component view = annotationManager.model2View(e.getAnnotation());
            annotationManager.getSelectionManager().setSelection(view, false);


            removeComponent(e.getAnnotation());
        }
    }
}
